home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------------;
- ; HILO.PRG ;
- ; ;
- ;This program demonstrates a method by which the screen resolution can be ;
- ;changed at a specific scan line. Using this method, the resolution can ;
- ;be changed from low to medium in the middle of the screen. Refer to ;
- ;the comments in the source code to see how it is done. ; ;
- ;-----------------------------------------------------------------------------;
- ;The following macro is needed because the assembler I am using will not
- ;generate these kinds of instructions automatically.
- ;
- ;MOVE.B #xxxx,$8aaa ;Short address move immediate
- ;
- MOVEBW MACRO
- DC.W $11FC
- DC.W \1
- DC.W \2
- ENDM
- ;
- TEXT
- ;----------
- ;Start here
- ;
- BEGADR EQU *
- ;
- MOVEM.L A0-A6/D0-D7,-(SP)
- ;
- ;Get into super mode
- ;
- CLR.L -(SP)
- MOVE.W #$20,-(SP)
- TRAP #1
- ADDQ #6,SP
- MOVE.L D0,SAVE_SSP
- ;-------------------------------
- ;Download character set from ROM
- ;into local memory. This is really not
- ;needed for the demonstration unless it is run
- ;on a machine with more than 512K.
- ;
- LEA CHTAB,A6 ;Address of where character bit maps are to be stored
- LEA ASCIT,A5 ;Ascii character codes
- MOVEQ #95,D7 ;96 characters
- ;
- CHLOP MOVE.B (A5)+,MSG+4 ;Have TOS display the character at (0,0)
- PEA MSG
- MOVE.W #$9,-(SP)
- TRAP #1
- ADDQ.L #6,SP
- ;
- MOVEQ #0,D0 ;Get screen address from the hardware
- MOVE.B $FF8201,D0
- SWAP D0
- MOVE.B $FF8203,D0
- LSL.W #8,D0
- MOVE.L D0,A4
- ;
- MOVEQ #7,D0 ;Move 8 bytes of bitmap data
- RASTLP MOVE.B (A4),(A6)+
- ADD.W #160,A4
- DBRA D0,RASTLP ;Go back for more bytes
- DBRA D7,CHLOP ;Go back for more characters
- ;--------------------------------------------------
- ;Clear frame buffer (the display will be at $78000)
- ;
- MOVE.W #7999,D0
- MOVE.L #$78000,A1
- MOVEQ #0,D1
- CLBL1 MOVE.L D1,(A1)+
- DBRA D0,CLBL1
- ;-------------------
- ;Save color pallette
- ;
- MOVE.L #$FF8240,A0
- LEA ORGPAL,A1
- MOVEQ #15,D0
- PALOP MOVE.W (A0)+,(A1)+
- DBRA D0,PALOP
- ;---------------
- ;Save resolution
- ;
- MOVE.B $FF8260,SAVREZ
- ;----------------------
- ;Save current address
- ;of display memory
- ;
- MOVE.B $FF8201,SVSCR
- MOVE.B $FF8203,SVSCR+1
- ;----------------------
- ;New pallette
- ;
- LEA PALET,A0
- MOVE.L #$FF8240,A1
- MOVEQ #15,D0
- PALOP2 MOVE.W (A0)+,(A1)+
- DBRA D0,PALOP2
- ;---------------------
- ;Disable certain 68901
- ;interupts.
- ;
- DSABL MOVE.W #5,-(SP) ;System timer
- MOVE.W #26,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #9,-(SP) ;RS232 transmit error
- MOVE.W #26,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #10,-(SP) ;RS232 transmit buffer empty
- MOVE.W #26,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #11,-(SP) ;RS232 receive error
- MOVE.W #26,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #12,-(SP) ;RS232 receive buffer full
- MOVE.W #26,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.L $466,D0 ;Wait for vertical blank
- W2 CMP.L $466,D0
- BEQ.S W2
- ;------------------------------------------------
- MOVEBW $07,$8201 ;Set display address to $78000
- MOVEBW $80,$8203
- ;
- MOVEBW $00,$8260 ;Set low rez
- ;------------------------------
- ;Fill screen with "A"
- ;
- MOVE #24,D7 ;25 lines
- LEA $78000,A1 ;Address of display memory
- ;
- OUTER MOVE.L A1,A2
- MOVE.W #159,D6 ;160 characters per line (all 4 planes)
- ;
- INNER LEA CHTAB,A0
- MOVE.W #(($41-$20)*8),D0
- LEA 0(A0,D0.W),A0 ;Address of bit map for "A"
- ;
- MOVE.B (A0)+,(A2) ;Move bit map
- MOVE.B (A0)+,160(A2)
- MOVE.B (A0)+,320(A2)
- MOVE.B (A0)+,480(A2)
- MOVE.B (A0)+,640(A2)
- MOVE.B (A0)+,800(A2)
- MOVE.B (A0)+,960(A2)
- MOVE.B (A0)+,1120(A2)
- ;
- ADDQ.W #1,A2
- DBRA D6,INNER
- ;
- ADD.W #1280,A1
- DBRA D7,OUTER
- ;-------------------------
- ;Replace Keyboard interupt
- ;vector.
- ;
- MOVE.L $118,KVEC
- LEA KINT,A0
- MOVE.L A0,$118
- ;--------------------
- ;Point timer B vector
- ;Leave timer disabled.
- ;
- PEA TIMERB ;Address of timer routine
- MOVE.W #$80,-(SP) ;Timer data register
- MOVE.W #0,-(SP) ;Timer control register (enabled and stopped)
- MOVE.W #1,-(SP) ;Select timer B
- MOVE.W #31,-(SP)
- TRAP #14
- ADD.W #12,SP
- ;------------------
- ;Replace system VBI
- ;with my own.
- ;
- MOVE.L $70,SYSVBI
- LEA VBI,A0
- MOVE.L A0,$70
- ;----------------------
- ;Bconstat - see if char
- ;was typed
- ;
- CHKEYS MOVE.W #2,-(SP)
- MOVE.W #1,-(SP)
- TRAP #13
- ADDQ.W #4,SP
- ;
- TST.W D0
- BEQ.S CHKEYS
- ;----------------------
- ;Bconin - read raw char
- ;
- MOVE.W #2,-(SP)
- MOVE.W #2,-(SP)
- TRAP #13
- ADDQ.W #4,SP
- ;
- CMP.B #3,D0 ;Cntrl-C ?
- BEQ EXITP
- ;
- MOVE.W D0,D1
- LSR.L #8,D0
- MOVE.B D1,D0
- ;--------------------------------
- CHKCUU CMP.W #$4800,D0 ;Cursor up
- BNE.S CHKCUD
- ;
- LEA CDATA,A0
- CMP.W #$0000,(A0) ;Can't move up if already at the top
- BEQ CHKEYS
- ;
- SUBQ.W #1,(A0) ;Modify timer B data register value (in VBI code)
- BRA CHKEYS
- ;----------------------------------
- CHKCUD CMP.W #$5000,D0 ;Cursor down
- BNE.S CHKEYS
- ;
- LEA CDATA,A0
- CMP.W #199,(A0) ;Can't move down if already at the bottom
- BEQ CHKEYS
- ;
- ADDQ.W #1,(A0) ;Modify timer B data register value (in VBI code)
- BRA CHKEYS
- ;-----------------
- ;Terminate program
- ;
- EXITP MOVE.L $466,D0 ;Wait for vertical blank
- W3 CMP.L $466,D0
- BEQ.S W3
- ;-----------------------------------------------------------------
- MOVE.L SYSVBI,$70 ;Restore system vertical blank interupt vector
- ;
- MOVE.L $466,D0 ;Wait for vertical blank
- W4 CMP.L $466,D0
- BEQ.S W4
- ;-------------------------------------------
- MOVE.L KVEC,$118 ;Restore keyboard vector
- ;
- ;Restore original address
- ;of display memory
- ;
- MOVE.B SVSCR,$FF8201
- MOVE.B SVSCR+1,$FF8203
- ;
- MOVEBW $00,$FA1B ;Clear control register for timer B
- ;--------------------
- ;Reset color pallette
- ;
- LEA ORGPAL,A0
- MOVE.L #$FF8240,A1
- MOVEQ #15,D0
- PALOP3 MOVE.W (A0)+,(A1)+
- DBRA D0,PALOP3
- ;------------------
- ;Restore resolution
- ;
- MOVE.B SAVREZ,$FF8260
- ;----------------------
- ;Re-enable 68901
- ;interupts.
- ;
- MOVE.W #5,-(SP) ;System timer
- MOVE.W #27,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #9,-(SP) ;RS232 transmit error
- MOVE.W #27,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #10,-(SP) ;RS232 transmit buffer empty
- MOVE.W #27,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #11,-(SP) ;RS232 receive error
- MOVE.W #27,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;
- MOVE.W #12,-(SP) ;RS232 receive buffer full
- MOVE.W #27,-(SP)
- TRAP #14
- ADDQ.W #4,SP
- ;---------------------
- ;Get out of super mode
- ;
- MOVE.L SAVE_SSP,-(SP)
- MOVE.W #$20,-(SP)
- TRAP #1
- ADDQ #6,SP
- ;------------------
- ;Terminate normally
- ;
- MOVEM.L (SP)+,A0-A6/D0-D7
- MOVE.W #0,-(A7)
- TRAP #1
- ;-----------------
- ;Keyboard interupt
- ;
- ;All we do here is change the
- ;priority of the keyboard interupt
- ;and jump to the original vector.
- ;
- KINT MOVE.W #$2500,SR
- KVEC EQU *+2
- JMP $10000 ;Self modifying long jump
- ;-------------------------------------
- ;Vertical blank interupt
- ;
- ;The timer B interupt will be
- ;set to start during the horizontal blank just
- ;before the scan line (specified in the timer B
- ;data register) is displayed. The screen resolution
- ;is set to low. Setting the timer B data register
- ;to zero does not work. Note that the instruction that
- ;sets the timer B data register is modified by the main program.
- ;The scan line number is relative to zero (i.e. 99 = 100th scan line)
- ;
- VBI MOVE.L D0,-(SP) ;Save register to be used
- ADDQ.L #1,$466 ;Update VBI count
- ;
- CDATA EQU *+2
- MOVE.W #99,D0 ;Data register for timer B (scan line 100)
- MOVE.B D0,$FFFA21
- ;
- ;Calculate low word of address to test for in TIMERB code
- ;This could be done with a lookup table for speed if needed.
- ;If the scan line (where the rez changes) does not need to be
- ;moved, this calculation can be done by the programmer and
- ;hard coded.
- ;
- ; (((D0+1)*160)-2)+$8000
- ;
- ADDQ.W #1,D0
- MULU #160,D0
- SUBQ.W #2,D0
- ADD.W #$8000,D0
- MOVE.W D0,TADDR
- ;----------------------------------------------------------------
- MOVEBW $08,$FA1B ;Control register for timer B (event counting)
- MOVEBW $00,$8260 ;Set low rez
- MOVE.L (SP)+,D0 ;Restore register
- RTE
- ;----------------
- ;Timer B interupt
- ;
- ;Change resolution at a certain scan line
- ;
- ;There are 3 registers that specify the current
- ;address of display memory that is being fetched.
- ;
- ; $FF8205 Video address pointer (high byte)
- ; $FF8207 Video address pointer (mid byte)
- ; $FF8209 Video address pointer (low byte)
- ;
- ;Because our display memory is located at $78000, only the mid and
- ;low bytes of these registers will change. Even though this interupt
- ;will be executed during the horizontal blank period just prior to
- ;the scan line specified in the timer B data register, it is not
- ;quite accurate enough to change the resolution at that point. The
- ;reason for this is that certain 68000 instructions can take 100+
- ;machine cycles to execute. This can cause the interupt to be delayed
- ;beyond the horizontal blank time period. To get around this problem,
- ;the video address pointer registers are used. When the interupt is
- ;executed, it executes a wait loop until the address of the last word
- ;of the scan line appears in the video address pointer registers, then
- ;the screen resolution is changed. This guarantees that the change
- ;will occur during horizontal blank.
- ;
- ;There are a few minor drawbacks to this method.
- ;
- ; 1. The resolution is changed beginning with the scan line
- ; after the one specified in the timer B data register.
- ; Zero cannot be used for the timer B data register.
- ; Therefore, the earliest the resolution can be changed is
- ; the third scan line.
- ;
- ; 2. This process will waste quite a few cycles waiting for the
- ; end of the scan line. This could be minimized in an application
- ; by having this interupt routine do some other quick task before
- ; starting the wait loop (ex. update sound registers).
- ;
- ; 3. Other interupts are disabled to insure that this one occurs at
- ; the right time. Some of the disabling might not be necessary.
- ; The developer's documentation describes a method that will still
- ; allow the system timer interupt to be used (sort of).
- ;
- ;This routine could easily be modified to change color registers as well.
- ;Note that the address value (used for comparison in the wait loop)
- ;is modified by the main program.
- ;
- TIMERB MOVE.L A0,-(SP) ;Save registers to be used
- MOVE.W D0,-(SP)
- ;
- CLR.W D0
- MOVE.W D0,A0
- ;
- EOLLP MOVEP.W -$7DF9(A0),D0 ;$FF8207 = Current display address (low word)
- TADDR EQU *+2
- CMP.W #$BE7E,D0 ;$8000+((100 * 160)-2) (end of 100th scan line)
- BCS.S EOLLP
- ;
- MOVEBW $01,$8260 ;Set medium rez
- MOVEBW $FE,$FA0F ;Clear in-service bit for timer B
- MOVEBW $00,$FA1B ;Clear control register for timer B
- ;
- MOVE.W (SP)+,D0 ;Restore registers
- MOVE.L (SP)+,A0
- RTE
- ;-----
- DATA
- CNOP 0,4
- ;----------------------------------------------------------
- ;Color pallette (all colors except background set to white)
- ;
- PALET DC.W $000,$777,$777,$777,$777,$777,$777,$777
- DC.W $777,$777,$777,$777,$777,$777,$777,$777
- ;---------------------------------------------
- SAVE_SSP DS.L 1 ;Save system stack pointer
- SYSVBI DS.L 1 ;Save system vbi address
- ORGPAL DS.W 16 ;Save original color pallette
- SAVREZ DS.W 1 ;Save system resolution value
- SVSCR DS.W 1 ;Save address of display memory
- ;----------------------------------------------
- CHTAB DS.B 96*8 ;ASCII character bit maps
- ;----------------------------------------
- ;By placing an ascii character code at
- ;MSG+4, and calling TOS, the character
- ;bit map will be drawn at (0,0).
- ;
- MSG DC.B $1B,'Y',$20,$20,0,0
- ;---------------------------
- ;ASCII characters
- ;
- ASCIT DC.B ' !""#$%&''()*+,-./'
- DC.B '0123456789:;<=>?'
- DC.B '@ABCDEFGHIJKLMNO'
- DC.B 'PQRSTUVWXYZ[\]^_'
- DC.B '`abcdefghijklmno'
- DC.B 'pqrstuvwxyz{|}~ '
- ;
- END
-